package efg;

import interfacesFerrovia.DefsGlobais.TipoAtributo;

import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 */
public class Switch extends RailwayElement {

	/**
	 * Trechos ligados a extremidade A da chave
	 */
	private Set<String> aTracks;
	
	/**
	 *  Trechoa ligagos a extremidade B da chave.
	 */
	private Set<String> bTracks;
	
	/**
	 * 
	 */
	public Map<Train, SwitchPeriod> schedule;

	public Switch(String id, Railway r) {
		super(r, id);
		assert (getId() != null);

		this.schedule = new HashMap<Train, SwitchPeriod>();

		this.aTracks = new HashSet<String>();
		for (String track : (String[]) getStaticAttribute(TipoAtributo.TRECHOS_A)) {
			assert (track != null);
			this.aTracks.add(track);
		}

		this.bTracks = new HashSet<String>();
		for (String track : (String[]) getStaticAttribute(TipoAtributo.TRECHOS_B)) {
			assert (track != null);
			this.bTracks.add(track);
		}

	}

	public int getScheduleEntriesNumber() {
		assert (schedule != null);
		return schedule.size();
	}

	public Map<Train, SwitchPeriod> getSchedule() {
		assert (schedule != null);
		return schedule;
	}

	public Set<String> getaTracks() {
		return aTracks;
	}

	public Set<String> getbTracks() {
		return bTracks;
	}

	public Integer getSwitchTime() {
		return (Integer) getStaticAttribute(TipoAtributo.TEMPO_MUDANCA);
	}

	public String getCurrentATrack() {
		return (String) getAttribute(TipoAtributo.ID_TR_CH_A);
	}

	public String getCurrentBTrack() {
		return (String) getAttribute(TipoAtributo.ID_TR_CH_B);
	}

	public Boolean getIsChanging() {
		return (Boolean) getAttribute(TipoAtributo.EM_MUDANCA);
	}

	public Integer getTimeUntilChange() {
		return (Integer) getAttribute(TipoAtributo.TEMPO_CONCLUSAO);
	}

	public SwitchPeriod getConflictPeriod(Float from, Float to) {
		assert (from < to);
		Float initial = from - (getSwitchTime() + 20);
		for (SwitchPeriod period : schedule.values()) {
			if (period.getStart() > to || period.getEnd() < initial)
				continue;
			return period;
		}
		return null;
	}

	public void allocTime(Train train, Float from, Float to) {
		assert (train != null);
		assert (!schedule.containsKey(train));
		SwitchPeriod concurrent = getConflictPeriod(from, to);
		assert (concurrent == null);
		SwitchPeriod newPeriod = new SwitchPeriod(train, from.intValue()
				- (getSwitchTime() + 20), to.intValue());
		schedule.put(train, newPeriod);
	}
}
